﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.IO;
using CCT.NUI.Visual;
using CCT.NUI.Core;
using CCT.NUI.Core.Clustering;
using CCT.NUI.HandTracking;
using CCT.NUI.Core.OpenNI;
using CCT.NUI.Core.Shape;
using CCT.NUI.Samples.ImageManipulation;
using CCT.NUI.KinectSDK;
using CCT.NUI.Core.Video;

namespace CCT.NUI.Samples
{
    public partial class MainForm : Form
    {
        private IDataSource dataSource = null;
        private IHandDataSource handDataSource = null;

        private IDataSourceFactory dataSourceFactory;

        private ClusterDataSourceSettings clusteringSettings = new ClusterDataSourceSettings();
        private ShapeDataSourceSettings shapeSettings = new ShapeDataSourceSettings();
        private HandDataSourceSettings handDetectionSettings = new HandDataSourceSettings();

        public MainForm()
        {
            InitializeComponent();

            this.FormClosing += new FormClosingEventHandler(MainForm_FormClosing);
        }

        private void buttonRGB_Click(object sender, EventArgs e)
        {
            this.SetImageDataSource(this.dataSourceFactory.CreateRGBBitmapDataSource());
        }

        private void buttonDepth_Click(object sender, EventArgs e)
        {
            this.SetImageDataSource(this.dataSourceFactory.CreateDepthBitmapDataSource());
        }

        private void buttonClustering_Click(object sender, EventArgs e)
        {
            this.SetClusterDataSource(this.dataSourceFactory.CreateClusterDataSource(this.clusteringSettings));
        }

        private void SetClusterDataSource(IClusterDataSource dataSource)
        {
            this.SetDataSource(dataSource, new ClusterLayer(dataSource));
        }

        private void SetHandDataSource(IHandDataSource dataSource)
        {
            this.SetDataSource(dataSource, new HandLayer(dataSource));
        }

        private void SetDataSource(IDataSource dataSource, ILayer layer)
        {
            this.Clear();
            this.dataSource = dataSource;
            this.videoControl.AddLayer(layer);
            dataSource.Start();
        }

        private void SetImageDataSource(IBitmapDataSource dataSource)
        {
            this.Clear();
            this.dataSource = dataSource;
            this.videoControl.SetImageSource(dataSource);
            dataSource.Start();
        }

        private void Clear()
        {
            if (this.dataSource != null)
            {
                this.dataSource.Stop();
            }
            this.videoControl.Clear();
        }

        void layer_RequestRefresh(object sender, EventArgs e)
        {
            this.videoControl.Invalidate();
        }

        void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            this.Clear();
        }

        private void buttonExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void linkLabelSource_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Process.Start("http://candescentnui.codeplex.com/");
        }

        private void linkLabelBlog_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Process.Start("http://blog.candescent.ch");
        }

        private void buttonHandAndFinger_Click(object sender, EventArgs e)
        {
            if (this.handDataSource == null)
            {
                this.handDataSource = new HandDataSource(this.dataSourceFactory.CreateShapeDataSource(this.clusteringSettings, this.shapeSettings), this.handDetectionSettings);
            }
            this.SetHandDataSource(this.handDataSource);
        }

        private void buttonSettings_Click(object sender, EventArgs e)
        {
            new SettingsForm(this.clusteringSettings, this.shapeSettings, this.handDetectionSettings).Show();
        }

        private void radioButtonSDK_CheckedChanged(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;
            if (this.radioButtonSDK.Checked)
            {
                try
                {
                    this.clusteringSettings.MaximumDepthThreshold = 950;
                    this.dataSourceFactory = new SDKDataSourceFactory();
                }
                catch (Exception exc)
                {
                    Cursor.Current = Cursors.Default;
                    MessageBox.Show(exc.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                this.ToggleButtons();
            }
            Cursor.Current = Cursors.Default;
        }

        private void ToggleButtons()
        {
            this.Enable(this.buttonClustering, this.buttonDepth, this.buttonRGB, this.buttonHandAndFinger, this.buttonImageManipulation, this.buttonHandDataFactory);
            this.Disable(this.radioButtonOpenNI, this.radioButtonSDK);
        }

        private void Enable(params Control[] controls)
        {
            this.SetEnabled(controls, true);
        }

        private void Disable(params Control[] controls)
        {
            this.SetEnabled(controls, false);
        }

        private void SetEnabled(IEnumerable<Control> controls, bool value)
        {
            foreach (var control in controls)
            {
                control.Enabled = value;
            }
        }

        private void radioButtonOpenNI_CheckedChanged(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;
            if (this.radioButtonOpenNI.Checked)
            {
                try
                {
                    this.dataSourceFactory = new OpenNIDataSourceFactory("Config.xml");
                }
                catch (Exception exc)
                {
                    Cursor.Current = Cursors.Default;
                    MessageBox.Show(exc.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                this.ToggleButtons();
            }
            Cursor.Current = Cursors.Default;
        }

        private void buttonImageManipulation_Click(object sender, EventArgs e)
        {
            var dataSource = new HandDataSource(this.dataSourceFactory.CreateShapeDataSource(this.clusteringSettings, this.shapeSettings));
            new ImageForm(dataSource).Show();
            dataSource.Start();
        }

        private void buttonHandDataFactory_Click(object sender, EventArgs e)
        {
            var factory = new HandDataFactory(new IntSize(640, 480));
            HandCollection handData;
            if (this.radioButtonOpenNI.Checked)
            {
                handData = factory.Create((this.dataSourceFactory as OpenNIDataSourceFactory).GetDepthGenerator().DataPtr);
            }
            else
            {
                handData = factory.Create((this.dataSourceFactory as SDKDataSourceFactory).Runtime.DepthStream.GetNextFrame(1000));
            }

            MessageBox.Show(string.Format("{0} hands detected", handData.Count), "Detection Message");
        }
    }
}
